package com.sunxd.zstudy.mybatise.infrastructure.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

/**
 * @author wangxinhua
 * Date: 2020/6/16 6:54 下午
 * Description: 自定义jacksonMapper
 */
public abstract class AbstractJacksonMapper {

    private final ObjectMapper mapper;
    protected final Logger log = LoggerFactory.getLogger(this.getClass());

    public AbstractJacksonMapper() {
        this.mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        this.mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//        this.mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        this.mapper.enable(SerializationFeature.INDENT_OUTPUT);
        this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//        addDateFormat("yyyy-MM-dd HH:mm:ss", "GMT+8", this.mapper);

        // 添加子类定义的序列化器
        addDeserializers(module);

        this.mapper.registerModule(module);
        this.mapper.registerModule(new GuavaModule());
    }

    /**
     * 获取默认的mapper
     *
     * @return mapper对象
     */
    public ObjectMapper defaultMapper() {
        return this.mapper;
    }

    public <T> T parse(String resourceName, Class<T> requestType) {
        try {
            try (
                    BufferedReader buffer = new BufferedReader(
                            new InputStreamReader(
                                    Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName)))
            ) {
                return mapper.readValue(buffer, requestType);
            }
        } catch (Exception e) {
            log.error("{} -> {}, {}", resourceName, requestType,
                    Throwables.getStackTraceAsString(e));
        }
        return null;
    }


    /**
     * 反序列化POJO或简单Collection如List<String>.
     * <p/>
     * 如果JSON字符串为Null或"null"字符串, 返回Null.
     * 如果JSON字符串为"[]", 返回空集合.
     * <p/>
     * 如需反序列化复杂Collection如List<MyBean>, 请使用fromJson(String,JavaType)
     */
    public <T> T fromJson(String jsonString, Class<T> clazz) {
        if (Strings.isNullOrEmpty(jsonString)) {
            return null;
        }
        try {
            return mapper.readValue(jsonString, clazz);
        } catch (IOException e) {
            log.warn("parse json string error {}, {}", jsonString, Throwables.getStackTraceAsString(e));
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T fromJson(String jsonString, JavaType javaType) {
        if (Strings.isNullOrEmpty(jsonString)) {
            return null;
        }
        try {
            return (T) mapper.readValue(jsonString, javaType);
        } catch (Exception e) {
            log.warn("parse json string error {}, {}", jsonString, Throwables.getStackTraceAsString(e));
            return null;
        }
    }

    public <T> T fromJson(String jsonString, TypeReference<T> typeReference) {
        if (Strings.isNullOrEmpty(jsonString)) {
            return null;
        } else {
            try {
                return this.mapper.readValue(jsonString, typeReference);
            } catch (Exception var4) {
                log.warn("parse json string error:" + jsonString, var4);
                return null;
            }
        }
    }

    /**
     * Object可以是POJO，也可以是Collection或数组。
     * 如果对象为Null, 返回"null".
     * 如果集合为空集合, 返回"[]".
     */
    public String toJson(Object object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (IOException e) {
            log.warn("write to json string error {}", object, Throwables.getStackTraceAsString(e));
            return null;
        }
    }

    /**
     * 子类增加自定义的json序列化解析器
     *
     * @param module
     */
    protected abstract void addDeserializers(SimpleModule module);

    private void addDateFormat(String dateFormat, String timeZoneStr, ObjectMapper MAPPER) {
        TimeZone timeZone = TimeZone.getDefault();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
                dateFormat);
        if (timeZone == null) {
            timeZone = new ObjectMapper().getSerializationConfig()
                    .getTimeZone();
        }
        simpleDateFormat.setTimeZone(timeZone);
        MAPPER.setDateFormat(simpleDateFormat);
        MAPPER.setTimeZone(timeZone);
    }
}
